/**
 *	@class			Jx.data.Model
 *	@description	creates record instance
 *						models the data from a result
 */
Jx.declare('Jx.data.Model', {

	$extend: 'Jx.Base',

	$requires: [

		'Jx.lib.Hash',
		
		'Jx.data.Manager'

	],

	$actions: [

		'setValue'

	],

	$cascadeCallback: function(Class, Base){

		var classFields = Class.prototype.fields,

			baseTypeClass = 'Jx.lib.Unit',

			fields = Jx.instantiate('Jx.lib.Hash'),

			definedFields = [],

			indexes = Class.$dataIndex = Jx.instantiate('Jx.lib.Hash'),
			
			baseIndex = Base.$dataIndex,
			
			primary = void(0),
			
			basePrimary = void(0);

		//-- auto inherit fields
		if (Jx.isArray(classFields)){

			for(var field, config, name, index, c = 0, l = classFields.length; c < l; c++){

				config = classFields[c];

				if (Jx.isObject(config) &&

					Jx.isString(name = config.name, true)

				){

					fields.set(name,

						field = Jx.instantiate(Class.prototype.schemaClass, [config])

					);

				}

			}

		}

		Class.prototype.fields = fields.applyIf( Base.prototype.fields );
		
		
		//-- register to Manager
		Jx.data.Manager.register(Class.$name);

	},

	$static: {

		declare: function(name, properties, publicized){

			if (Jx.isString(name, true) && Jx.isObject(properties)){

				if (!Jx.isString(properties.$extend, true)){

					properties.$extend = this.$name;

				}

				Jx[

					publicized !== false ?

						'declare'

						:

						'categorize'

				]( name, properties );

			}

		},
		
		getFields: function(){

			return this.prototype.fields;

		}

	},


	$shortcuts: {

		'Jx': {

			'createModel': 'declare'

		}

	},

	fields: [],

	constructor: function(data){
		
		//-- initialize values
		this.initializeValues();

		this.$super(arguments);

	},
	
	initializeValues: function(){
		
		for(var fields = this.fields, l = fields.length; l--;){
			
			fields.get( fields[l] ).initializeValue( this );
			
		}
		
	},
	
	getValue: function(name){
		
		var field = this.fields.get(name),
		
			value = this.get(name);
		
		return field ?
			
			value[ field.getterMethod() ].apply( value, field.getterParams() || [] )
			
			:
			
			value;
		
	},
	
	onSetValue: function(operation, name, value){
		
		var field = operation.field,
		
			unit = operation.unit;
		
		if ( this.fields.isSet(name) ){

			this.get(name).setValue(value);
			
			operation.value = this.getValue(name);
			
		} else {
			
			this.set(value);
			
		}
		
	},
	
	onAfterSetValue: function(operation, name){
		
		this.dispatch( 'update', name, operation.value, operation.old );
		
	},
	
	allowSetValue: function(operation, name, value){
		
		var allow = Jx.isString(name, true);
		
		if (allow){
				
			operation.old = this.getValue(name);
			
			operation.value = value;
			
		}
		
		return allow;
		
	}






});
